package cn.ac.iscas.service.component;

import cn.ac.iscas.base.utils.OkHttpClientUtils;
import cn.ac.iscas.config.MiddlePlatformConfig;
//import cn.ac.iscas.dao.api.ComponentMetadataRepository;
import cn.ac.iscas.dao.IComponentMetadataDao;
import cn.ac.iscas.dao.entity.ComponentMetadataDO;
//import cn.ac.iscas.dao.impl.EtlComponentDao;
//import cn.ac.iscas.dao.impl.EtlFileDao;
import cn.ac.iscas.domain.component.ComponentType;
import cn.ac.iscas.domain.response.middleplatform.DmoTableMeta;
import cn.ac.iscas.domain.view.ComponentView;
import cn.ac.iscas.domain.view.CtrlType;
import cn.ac.iscas.domain.view.ParameterItem;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iscas.datasong.lib.common.DataSongException;
import com.iscas.datasong.lib.common.Status;
import com.iscas.datasong.lib.common.column.ColumnType;
import com.iscas.datasong.lib.util.DataSongJsonUtils;
import com.iscas.datasong.lib.util.DataSongStringUtils;
import com.iscas.templet.view.tree.TreeResponseData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

/**
 * @author LJian
 * @version 1.0
 * @description: TODO
 * @date 2022/7/22 8:37
 */
@Service
public class ComponentService {
    @Autowired
    private IComponentMetadataDao componentMetadataDao;
    //private IComponentMetadataMapper IComponentMetadataMapper;

//    @Autowired
//    ComponentMetadataRepository componentMetadataRepository;

    @Autowired
    private MiddlePlatformConfig middlePlatformConfig;

//    @Autowired
//    EtlFileDao etlFileDao;

    ///@Autowired
    ///EtlComponentDao etlComponentDao;

    private OkHttpClientUtils httpClient = new OkHttpClientUtils();

    public ComponentMetadataDO getComponent(String id) throws DataSongException {
        ///return componentMetadataRepository.findOne(id);
        return componentMetadataDao.selectById(id);
    }

    public List<ComponentMetadataDO> getComponentList(String type, String modelType) throws DataSongException {
        if(DataSongStringUtils.isNotEmpty(modelType) && DataSongStringUtils.isEmpty(type)){
            throw new DataSongException("param is empty","父类型不能为空！");
        }

        ///return etlComponentDao.getAllSimpleComponents(type, modelType);
        return componentMetadataDao.select(type, modelType);
    }

    public TreeResponseData getTypeTree( boolean allLevel, String authorization) {
        List<DmoTableMeta> dataModels = getAllDataModel(authorization);
        TreeResponseData root = new TreeResponseData();
        root.setId("root");
        root.setLabel("组件");

        List<ComponentMetadataDO> componentMetadataList = componentMetadataDao.selectAll();

        List<TreeResponseData> childrenOne = new ArrayList<>();
        for( ComponentType componentType : ComponentType.values()){
            TreeResponseData item = new TreeResponseData();
            item.setLabel(componentType.value());
            item.setId(componentType.name());
            childrenOne.add(item);

            if(componentType == ComponentType.analyzer){
                List<TreeResponseData>  childrenTwo = getModelTypes(componentMetadataList, allLevel);
                item.setChildren(childrenTwo);
            }else{
                if(allLevel){
                    item.setData(getByComponentType(componentType, componentMetadataList));
                }
            }
        }

        for ( DmoTableMeta dataModel : dataModels) {
            TreeResponseData item = new TreeResponseData();
            item.setLabel("数据模型");
            if (dataModel.getTableAlias() != null && !dataModel.getTableAlias().isEmpty()) {
                item.setId(dataModel.getTableAlias());
            } else {
                item.setId(dataModel.getTableName());
            }
            item.setData(dataModel);
            childrenOne.add(item);
        }
        root.setChildren(childrenOne);

        return root;
    }

    public TreeResponseData getTypeTreeByType(boolean allLevel, String taskType, String authorization) {
        List<DmoTableMeta> dataModels = getAllDataModel(authorization);
        TreeResponseData root = new TreeResponseData();
        root.setId("root");
        root.setLabel("组件");

        //List<ComponentMetadataDO> componentMetadataList = componentMetadataDao.selectAll();
        List<ComponentMetadataDO> componentMetadataList = componentMetadataDao.selectByCategory(taskType);

        List<TreeResponseData> childrenOne = new ArrayList<>();
        for( ComponentType componentType : ComponentType.values()){
            TreeResponseData item = new TreeResponseData();
            item.setLabel(componentType.value());
            item.setId(componentType.name());
            childrenOne.add(item);

            if(componentType == ComponentType.analyzer){
                List<TreeResponseData>  childrenTwo = getModelTypes(componentMetadataList, allLevel);
                if (childrenTwo == null || childrenTwo.isEmpty()) {
                    continue;
                }
                item.setChildren(childrenTwo);
            }else{
                if(allLevel){
                    List<ComponentMetadataDO>  children = getByComponentType(componentType, componentMetadataList);
                    if (children == null || children.isEmpty()) {
                        continue;
                    }
                    item.setData(getByComponentType(componentType, componentMetadataList));
                }
            }
        }

        if (dataModels != null && dataModels.size() > 0) {
            for (DmoTableMeta dataModel : dataModels) {
                if (taskType != null && !taskType.trim().equalsIgnoreCase("flink")) {
                    if (!dataModel.getDatasourceType().toLowerCase().contains(taskType.toLowerCase())) {
                        continue;
                    }
                }
                TreeResponseData item = new TreeResponseData();
                item.setLabel("数据模型");
                if (dataModel.getTableAlias() != null && !dataModel.getTableAlias().isEmpty()) {
                    item.setId(dataModel.getTableAlias());
                } else {
                    item.setId(dataModel.getTableName());
                }
                item.setData(dataModel);
                childrenOne.add(item);
            }
        }
        root.setChildren(childrenOne);

        return root;
    }

    /**
     * 获取模型的二级分类
     * @param componentMetadataList
     * @return
     */
    private List<TreeResponseData> getModelTypes(List<ComponentMetadataDO> componentMetadataList, boolean allLevel ){
        Map<String, List> childrenMap = new HashMap<>() ;
        for(ComponentMetadataDO componentMetadata : componentMetadataList){
            if(componentMetadata.getType().equals(ComponentType.analyzer.name())){
                if(childrenMap.containsKey(componentMetadata.getModelType())) {
                    childrenMap.get(componentMetadata.getModelType()).add(componentMetadata);
                }else{
                    List<ComponentMetadataDO> tmpList = new ArrayList<>();
                    tmpList.add(componentMetadata);
                    childrenMap.put(componentMetadata.getModelType(), tmpList);
                }
            }
        }

        List<TreeResponseData> treeResponseDatas = new ArrayList<>();
        for(String modelType : childrenMap.keySet()){
            TreeResponseData data = new TreeResponseData( );
            data.setId(modelType);
            data.setLabel(modelType);

            if(allLevel){
                data.setData(childrenMap.get(modelType));
            }

            treeResponseDatas.add(data);
        }

        return treeResponseDatas;
    }

    /**
     * 根据类型获取所有组件
     * @param type
     * @param componentMetadataList
     * @return
     */
    private List<ComponentMetadataDO>  getByComponentType(ComponentType type, List<ComponentMetadataDO> componentMetadataList ){
        List<ComponentMetadataDO> treeResponseDatas = new ArrayList<>();
        if (componentMetadataList == null ) {
            return treeResponseDatas;
        }
        for(ComponentMetadataDO componentMetadata : componentMetadataList){
            if(componentMetadata.getType().equals(type.name())){
                treeResponseDatas.add(componentMetadata);
            }
        }

        return treeResponseDatas;
    }

    private List<DmoTableMeta> getAllDataModel(String authorization) {
        List<DmoTableMeta> dataModels = new ArrayList<>();
        Map<String, Integer> page = new HashMap<>(4);
        page.put("pageNumber", 1);
        page.put("pageSize", Integer.MAX_VALUE);
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", authorization);
            String response = httpClient.doPost(middlePlatformConfig.getQueryAllDataModelsUrl(),
                    headers,
                    DataSongJsonUtils.toJson(page));

            Map<String, Object> responseMap = DataSongJsonUtils.fromJson(response, Map.class);
            if (responseMap.containsKey("value")) {
                List<Map<String, Object>> datas = (List<Map<String, Object>>) ((Map)responseMap.get("value")).get("data");
                if (datas != null) {
                    for (Map<String, Object> data : datas) {
                        dataModels.add(new ObjectMapper().convertValue(data, DmoTableMeta.class));
                    }
                }
            } else {
                return null;
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (DataSongException e) {
            e.printStackTrace();
        }
        return dataModels;
    }

    public Map<String, Object> getDataSourceByDataModel(String dataModel) {
        String url = middlePlatformConfig.getQueryDataSourceByDataModelUrl() + dataModel;
        Map<String, Object> result = null;
        try {
            String response = httpClient.doGet(url);
            Map<String, Object> responseMap = DataSongJsonUtils.fromJson(response, Map.class);
            if (responseMap.containsKey("value")) {
                //result = new ObjectMapper().convertValue(responseMap.get("value"), DmoDatasource.class);
                result = (Map<String, Object>) responseMap.get("value");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DataSongException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 保存组件
     * @param componentMetadata
     * @return
     * @throws DataSongException
     */
    public String saveComponent(ComponentMetadataDO componentMetadata) throws DataSongException {
        //检查组件的各种配置
        if(componentMetadata == null){
            throw new DataSongException(Status.PARAM_ERROR, "组件不能为null！");
        }

        if(DataSongStringUtils.isEmpty(componentMetadata.getAlgorithm()) ){
            throw new DataSongException(Status.PARAM_ERROR, "组件algorithm不能都为空！");
        }

        if(DataSongStringUtils.isEmpty(componentMetadata.getEntryClassName())){
            componentMetadata.setEntryClassName(componentMetadata.get_id());
        }

//        if(DataSongStringUtils.isEmpty(componentMetadata.getViewParameter())){
//            throw new DataSongException(Status.PARAM_ERROR, "组件的可视化参数不能都为空！");
//        }

        if(DataSongStringUtils.isEmpty(componentMetadata.getViewParameter())){
            //throw new DataSongException(Status.PARAM_ERROR, "组件的可视化参数不能都为空！");
        }else{
            if(ComponentType.analyzer.name().equals(componentMetadata.getType())) {
                ComponentView componentView = DataSongJsonUtils.fromJson((String) componentMetadata.getViewParameter(), ComponentView.class);
                if(componentView == null || componentView.getParameters()==null || componentView.getParameters().size() == 0){
                    throw new DataSongException(Status.PARAM_ERROR.name(),"模型组件的参数不能为空！");
                }
                for(ParameterItem item : componentView.getParameters()){
                    if(DataSongStringUtils.isEmpty(item.getId())){
                        throw new DataSongException(Status.PARAM_ERROR.name(),"模型组件参数的[id]值不能为空！");
                    }
                    if(DataSongStringUtils.isEmpty(item.getLabel())){//label为空，则默认设置为id
                        item.setLabel(item.getId()+"值");
                    }
                    if(DataSongStringUtils.isEmpty(item.getTips())){//tips为空，则默认设置一个
                        item.setTips("请输入"+item.getId());
                    }

                    //设置组件类型 和 必填
                    if(item.getCtrltype() == null) {
                        if (DataSongStringUtils.isNotEmpty(item.getGroup())) {// 为前台自己拼装
                            item.setCtrltype(CtrlType.rdropdown);
                            item.setRequired(true);
                        } else {
                            item.setCtrltype(CtrlType.text);
                        }
                    }

                    //设置valuetype
                    if(item.getValuetype() == null){
                        item.setValue(ColumnType.String);
                    }
                }
            }
        }

        if(DataSongStringUtils.isEmpty(componentMetadata.getModelType())){
            componentMetadata.setModelType("其他");
        }

//        if(DataSongStringUtils.isNotEmpty(componentMetadata.getModelLocalPath())){
//
//            File file = new File(etlConfigure.getModelPath()+componentMetadata.getModelLocalPath());
//            if(!file.exists()) {
//                throw new DataSongException(Status.PARAM_ERROR, String.format("模型文件[%s]不存在！", componentMetadata.getModelLocalPath()));
//            }
//
//            //发布到datasong中
//            String fileId = etlFileDao.uploadModelFile(etlConfigure.getModelPath()+componentMetadata.getModelLocalPath());
//            componentMetadata.setModelPublishPath(fileId);
//        }


        //默认为数据挖掘类型
        if(DataSongStringUtils.isEmpty(componentMetadata.getType())){
            componentMetadata.setType(ComponentType.analyzer.name());
        }
        componentMetadata.setCreateTime(Date.from(ZonedDateTime.now(ZoneId.of("Asia/Shanghai")).toInstant()));

        if(DataSongStringUtils.isEmpty(componentMetadata.getEntryClassName())){
            componentMetadata.setEntryClassName(componentMetadata.get_id());
            //componentMetadataRepository.save(componentMetadata);
        }
        //String id =  componentMetadataRepository.save(componentMetadata);
        int res = componentMetadataDao.save(componentMetadata);
        String id = "";
        if (res == 1) {
            id = componentMetadata.get_id();
        }
        return id;
    }

    /**
     * 保存组件
     * @param id
     * @return
     * @throws DataSongException
     */
    public boolean deleteComponent(String id) throws DataSongException {
        //检查组件的各种配置
        if(id == null){
            throw new DataSongException(Status.PARAM_ERROR, "参数id不能为空！");
        }
        List<String> ids = Arrays.asList(id.split(","));
        boolean res = true;
        //return componentMetadataRepository.deleteIdBatch(ids)>=0;
        if (ids.size() != componentMetadataDao.deleteByIds(ids)) {
            res = false;
        }
        return res;
    }
}
